package com.winchain.chainbill.bill.biz.transfer.rx;

import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.persistence.transaction.Transaction;
import com.shell.bee.persistence.transaction.TransactionUtil;
import com.shell.framework.command.CallbackContext;
import com.shell.framework.command.ChainBase;
import com.shell.framework.command.CommandContext;
import com.shell.framework.rx.OnErrorNotImplementedSubscriber;
import com.shell.framework.utils.SysDateUtil;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillTranEvent;
import com.winchain.chainbill.bill.biz.contract.cmd.ContractSignCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillHldrCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvDfrlCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillMoveCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillOptCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillTimeoutCmd;
import com.winchain.chainbill.bill.biz.send.rx.BatchBillEvent;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillRcv4PrntCmd;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillRcv4XfeCmd;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillXfeCertCmd;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillXfeCmd;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillXfeMsgCmd;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillXfeStatsCmd;
import com.winchain.chainbill.bill.biz.transfer.service.BillXfeEventService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BillXfeRevPassSubscriber extends OnErrorNotImplementedSubscriber<BatchBillEvent<String, CbXfe>> {
	@Autowired
	private BillTimeoutCmd<CbXfe> billTimeoutCmd;
	@Autowired
	private BillOptCmd<CbXfe> billOptCmd;
	@Autowired
	private BillXfeCmd billXfeCmd;
	@Autowired
	private BillMoveCmd<CbXfe> billMoveCmd;
	@Autowired
	private BillXfeStatsCmd billXfeStatsCmd;
	@Autowired
	private BillRcvDfrlCmd<CbXfe> billDfrlCmd;
	@Autowired
	private BillXfeMsgCmd billXfeMsgCmd;
	@Autowired
	private BillRcv4XfeCmd billRcv4TransferCmd;
	@Autowired
	private BillHldrCmd<CbXfe> billHldrCmd;
	@Autowired
	private BillRcv4PrntCmd<CbXfe> billRcv4PrntCmd;
	@Autowired
	private BillXfeCertCmd billXfeCertCmd;
	@Autowired
	private BillXfeEventService billXfeEventService;
	@Autowired
	private ContractSignCmd<CbXfe> contractSignCmd;

	public void onApplicationEvent(final BatchBillEvent<String, CbXfe> t) {
		List<String> records = t.getRecs();
		BatchBillStats<CbXfe> stats = t.getStats();

		final Bill<CbXfe> source = new Bill();
		for (final String record : records) {
			try {
				if (t.isNewTransaction()) {
					TransactionUtil.execute(new Transaction() {
						public void doInTransaction() {
							BillXfeRevPassSubscriber.this.done(t, source, record);
						}
					}, new int[0]);
				} else {
					done(t, source, record);
				}
				stats.addPassedRecord(source);
			} catch (Exception e) {
				e.printStackTrace();
				stats.addAbnormalRecord(source);
				stats.addAbnormalMsg(e.getMessage());
			}
		}
	}

	private void done(BatchBillEvent<String, CbXfe> t, Bill<CbXfe> source, String record) {
		BillTranEvent<CbXfe> event = this.billXfeEventService.getBillTranEvent(record, false);

		Bill<CbXfe> prntBill = event.getBill();

		List<Bill<CbXfe>> children = (List<Bill<CbXfe>>) event.getChildren();
		if (children.size() > 0) {
			t.getOperation().setOptCode("EX13");
			t.getOperation().setRemark("������������");
		} else if (bookXfe((CbXfe) event.getBill().getSource())) {
			t.getOperation().setOptCode("EX17");
			t.getOperation().setRemark("����������������");
		} else {
			t.getOperation().setOptCode("EX11");
		}
		source.setRec(event.getBill().getRec());
		source.setSource(event.getBill().getSource());

		CommandContext<Bill<CbXfe>> context = new CommandContext();
		context.setSource(prntBill);
		context.setValue("Operation", t.getOperation());
		context.setValue("TimeoutOperation", t.getTimeoutOpt());

		context.setValue("bizType", "cb_xfe_rev");
		context.setValue("children", children);
		String phoneCode = t.getStringValue("phoneCode");
		context.setValue("phoneCode", phoneCode);

		ChainBase<Bill<CbXfe>> crb = new ChainBase();
		crb.add(this.billTimeoutCmd);
		crb.add(this.billOptCmd);

		crb.add(this.billXfeStatsCmd);
		if (((CbXfe) prntBill.getSource()).getXfeId() != null) {
			if (!ChainBillUtil.signContOnline()) {
				crb.add(this.contractSignCmd);
			}
			crb.add(this.billXfeCmd);
			crb.add(this.billDfrlCmd);
			crb.add(this.billRcv4TransferCmd);

			crb.add(this.billXfeMsgCmd);
		}
		crb.add(this.billMoveCmd);
		crb.execute(context);
		if (children.size() > 0) {
			billXfeRevPassChd(children, phoneCode);
		}
	}

	private void billXfeRevPassChd(List<Bill<CbXfe>> child, String phoneCode) {
		String createTime = null;
		for (Bill<CbXfe> bill : child) {
			CbXfe cbXfe = (CbXfe) bill.getSource();
			String ct = cbXfe.getCreateTime();
			if ((createTime == null) && (ct != null) && (!"".equals(ct))) {
				createTime = ct;
			}
		}
		for (Bill<CbXfe> bill : child) {
			((CbXfe) bill.getSource()).setCreateTime(createTime);

			CbOpt opt = new CbOpt();
			if (((CbXfe) bill.getSource()).getXfeId() == null) {
				opt.setCurState("S000");
				opt.setOptCode("E502");
				opt.setRemark("������������");
			} else if (bookXfe((CbXfe) bill.getSource())) {
				opt.setCurState("S000");
				opt.setOptCode("EX17");
				opt.setRemark("����������������");
			} else {
				opt.setCurState("S000");
				opt.setOptCode("E501");
				opt.setRemark("������������");
			}
			CallbackContext<Bill<CbXfe>, AcctTxRec> context = new CallbackContext();
			context.setSource(bill);
			context.setValue("Operation", opt);
			context.setValue("bizType", "cb_xfe_rev");
			context.setValue("phoneCode", phoneCode);

			ChainBase<Bill<CbXfe>> crb = new ChainBase();
			crb.add(this.billOptCmd);
			if (((CbXfe) bill.getSource()).getXfeId() == null) {
				String buyerId = null;
				String buyerName = null;
				for (Bill<CbXfe> billChd : child) {
					if (((CbXfe) billChd.getSource()).getXfeId() != null) {
						buyerId = ((CbXfe) billChd.getSource()).getBuyerId();
						buyerName = ((CbXfe) billChd.getSource()).getBuyerNm();
						break;
					}
				}
				context.setValue("OwnerId", buyerId);
				context.setValue("OwberName", buyerName);
				crb.add(this.billHldrCmd);
				crb.add(this.billRcv4PrntCmd);

				crb.add(this.billXfeCertCmd);
			}
			if (((CbXfe) bill.getSource()).getXfeId() != null) {
				if (!ChainBillUtil.signContOnline()) {
					crb.add(this.contractSignCmd);
				}
				crb.add(this.billXfeCmd);
				crb.add(this.billDfrlCmd);
				crb.add(this.billRcv4TransferCmd);
				crb.add(this.billXfeMsgCmd);
			}
			crb.add(this.billMoveCmd);

			crb.execute(context);
		}
	}

	private boolean bookXfe(CbXfe cbXfe) {
		boolean bookXfe = false;

		String xfeDate = cbXfe.getXfeDate();
		String revDate = DateUtil.getSystemDate();
		if (SysDateUtil.compare(xfeDate, revDate) == 1) {
			bookXfe = true;
		}
		return bookXfe;
	}
}
